#!/usr/bin/env bash

include "libs/database.sh"
include "libs/ohos.sh"
include "libs/output.sh"

function docker:build()
{
    if docker build -t=ohos $OHOS_TOOL/build_docker/; then
        database:global_load
        database:global_set docker_version 0
        database:global_save
    else
        return 1
    fi
}

function docker:is_image_exist()
{
    (( $(docker image ls "$1" | wc -l) >= 2 ))
}

function docker:create()
{
    #local path=$1
    #local name=$2
    local amount_of_cpu="$(cat /proc/cpuinfo | grep "^processor" | wc -l)"
    amount_of_cpu="${amount_of_cpu:-4}"
    local amount_of_mem="$(cat /proc/meminfo | grep "^MemTotal:" | awk '{print $2}')"
    amount_of_mem="${amount_of_mem:-$((4 * 1024 * 1024))}"

    (( amount_of_cpu = amount_of_cpu * 3 / 4 ))
    (( amount_of_mem = amount_of_mem * 3 / 4 ))
    docker run \
        -tid \
        -v "$1:/std" \
        --name=$2 \
        --user=user \
        --memory="${amount_of_mem}K" \
        --cpuset-cpus="0-$((amount_of_cpu - 1))" \
        ohos:latest bash
}

function docker:reset()
{
    #local path=$1
    #local name=$2
    docker rm -f "$2" >/dev/null || return
    docker:create "$1" "$2"
}

function docker:simple_exec()
{
    docker exec -it $(ohos:get_repo_name) bash -c "$*"
}

function docker:update()
{
    local apt="sudo apt install -y"
    local pip="pip install -i https://pypi.tuna.tsinghua.edu.cn/simple"
    local sh=""
    local docker_updates=(
       apt "zip"
       apt "ruby"
       apt "img2simg"
       apt "ccache"
       apt "genext2fs"
       apt "libssl-dev"
       apt "liblz4-tool"
       apt "cpio"
       apt "python3-pip"
       pip "pyyaml"
       pip "requests"
       pip "prompt_toolkit==1.0.15"
       apt "openjdk-8-jdk"
       apt "python-is-python3"
       sh  "sudo rm /usr/bin/python; sudo ln -sf python3 /usr/bin/python"
    )

    local retval=0
    local updated=false
    local apt_updated=false

    database:global_load
    version=$(database:global_get docker_version)

    while (( version < ${#docker_updates[*]} / 2 )); do
        local docker_sources="${docker_updates[$(($version * 2 + 0))]}"
        local docker_package="${docker_updates[$(($version * 2 + 1))]}"
        local docker_command="${!docker_sources} $docker_package"

        # apt update
        if ! $apt_updated && [ "$docker_sources" == "apt" ]; then
            output:logd "updating apt sources"
            if docker:simple_exec "sudo apt update"; then
                output:logi "update success"
                apt_updated=true
            else
                output:loge "update failed"
                retval=1
                break
            fi
        fi

        # update
        output:logd "updating version[$version] $docker_package"
        if docker:simple_exec "$docker_command"; then
            output:logi "update success"
        else
            output:loge "update failed"
            retval=1
            break
        fi

        updated=true
        (( ++version ))
    done

    if $updated; then
        # apt remove
        if $apt_updated; then
            output:logd "autoremoveing apt useless packages"
            if docker:simple_exec "sudo apt autoremove -y"; then
                output:logi "autoremove success"
            else
                output:loge "autoremove failed"
            fi
        fi

        # commit
        output:logd "committing ohos:latest"
        if docker commit $(ohos:get_repo_name) ohos:latest 1>/dev/null; then
            output:logi "commit success"
        else
            output:loge "commit failed"
            return 1
        fi

        # prune
        output:logd "pruning image"
        if docker image prune -f; then
            output:logi "prune success"
        else
            output:loge "prune failed"
        fi

        database:global_load
        database:global_set docker_version "$version"
        database:global_save
    fi

    return $retval
}

function docker:maybe_reset()
{
    database:repo_load || return
    repo_version="$(database:repo_get docker_version)"
    global_version="$(database:global_get docker_version)"
    if [ "$repo_version" != "$global_version" ]; then
        output:logd "reseting docker"
        if docker:reset $(ohos:get_repo_path) $(ohos:get_repo_name); then
            database:repo_set docker_version "$global_version"
            database:repo_save
            output:logi "docker reset from $repo_version to $global_version success"
        else
            output:loge "reset failed"
            return 1
        fi
    fi
}

function docker:exec()
{
    ohos:cd_repo || return
    if [ "$OHOS_DOCKER_USE" == "true" ]; then
        if ! docker start $(ohos:get_repo_name) >/dev/null 2>&1; then
            docker:create $(ohos:get_repo_path) $(ohos:get_repo_name) || return
            docker start $(ohos:get_repo_name) >/dev/null 2>&1 || return
        fi

        docker:update || return
        docker:maybe_reset || return
        docker:simple_exec "cd /std/; cd $DOCKER_CWD; $(ohos:get_env /std); $*" || return
    else
        eval $(ohos:get_env $(pwd))
        cd $DOCKER_CWD
        $*
    fi
}
